<?php

class Crud_Event
{
	/**
	 * @var Crud_Event
	 */
	protected static $_instance;

	/**
	 * @return Crud_Event
	 */
	public static function getInstance()
	{
		if (!self::$_instance) {
			self::$_instance = new self();
		}
		return self::$_instance;
	}
	
	private function __construct() {}
	
	/**
	 * Handlers array.
	 * @var array
	 */
	protected $_handlers = array();
	
	/**
	 * Добавляет в стек все обработчики, определенные для переданного раздела.
	 * Обращается к БД, чтобы все их вытащить.
	 * 
	 * @param Crud_Section $section
	 * @return void
	 */
	public function addHandlersBySection($section)
	{
		$rowset = $section->getAdminSectionHandlerRowsetBySectionId();
		foreach ($rowset as $row) {
			$this->addHandler($row->getClassName());
		}
	}
	
	/**
	 * Add event handler to chain.
	 * 
	 * @param Crud_Event_Handler $handler
	 * @return Crud_Event
	 */
	public function addHandler($handler) 
	{
		if (!$handler instanceof Crud_Event_Handler) {
			$handler = new $handler();
		}
		
		$type = $handler->getType();
		$this->_handlers[$type][] = $handler;
		return $this;	
	}
	
	/**
	 * Set event handlers array.
	 * Clean chain before setting.
	 * 
	 * @param array|Crud_Event_Handler $handlers
	 * @return Crud_Event
	 */
	public function setHandlers($handlers)
	{
		$this->cleanHandlers();
		
		if (!is_array($handlers)) {
			$handlers = array($handlers);
		}
		
		foreach ($handlers as $handler) {
			$this->addHandler($handler);
		}
		
		return $this;
	}
	
	/**
	 * Clean handlers chain.
	 * 
	 * @return Crud_Event
	 */
	public function cleanHandlers()
	{
		$this->_handlers = array();
		return $this;
	}
	
	/**
	 * Return handlers array.
	 * Optional given type.
	 * 
	 * @param string $type
	 * @return array
	 */
	public function getHandlers($type = null)
	{
		if ($type) {
			if (isset($this->_handlers[$type])) {
				return $this->_handlers[$type];
			}
			
			return array();
		}
		
		return $this->_handlers;
	}
	
	/**
	 * Return handler by type.
	 * 
	 * @param string $type
	 * @return array
	 */
	public function getHandler($type)
	{
		return current($this->getHandlers($type));
	}
	
	/**
	 * Run all handlers by type.
	 * 
	 * @param string $type
	 * @param array $options
	 * @return Crud_Event
	 */
	public function runHandlers($type, $options = array())
	{
		$return = true;
		$handlers = $this->getHandlers($type);
		foreach ($handlers as $handler) {
			if (!$handler->run($options)) {
				$return = false;
			}
		}
		
		return $return;
	}
}